module event_sync;

    // 事件声明
    event stage1_done, stage2_done, final_done;
    event error_occurred;

    // 进程 1: 执行阶段 1，然后触发 stage1_done
    initial begin : process_stage1
        $display("[%0t] Stage 1: Starting work...", $time);
        #10; // 模拟工作耗时
        $display("[%0t] Stage 1: Work done. Triggering 'stage1_done'.", $time);
        -> stage1_done; // 非阻塞触发
        $display("[%0t] Stage 1: Trigger sent. Continuing...", $time);
        #5;
        $display("[%0t] Stage 1: Finished.", $time);
    end

    // 进程 2: 等待 stage1_done (使用 @)，执行阶段 2，触发 stage2_done
    initial begin : process_stage2
        $display("[%0t] Stage 2: Waiting for 'stage1_done'...", $time);
        @stage1_done; // 阻塞等待 stage1_done 事件被触发
        $display("[%0t] Stage 2: Received 'stage1_done'. Starting work...", $time);
        #15; // 模拟工作耗时
        $display("[%0t] Stage 2: Work done. Triggering 'stage2_done'.", $time);
        -> stage2_done; // 非阻塞触发
        $display("[%0t] Stage 2: Finished.", $time);
    end

    // 进程 3: 等待 stage2_done (使用 @)，执行最终阶段，触发 final_done
    initial begin : process_stage3
        $display("[%0t] Stage 3: Waiting for 'stage2_done'...", $time);
        @stage2_done; // 阻塞等待 stage2_done 事件被触发
        $display("[%0t] Stage 3: Received 'stage2_done'. Starting final work...", $time);
        #10; // 模拟工作耗时

        // 模拟可能发生的错误
        if ($urandom_range(0, 10) % 2 == 1) begin // 50% 概率触发错误
            $display("[%0t] Stage 3: ERROR occurred! Triggering 'error_occurred'.", $time);
            -> error_occurred;
        end else begin
            $display("[%0t] Stage 3: Final work done. Triggering 'final_done'.", $time);
            -> final_done; // 非阻塞触发
        end
        $display("[%0t] Stage 3: Finished.", $time);
    end

    // 进程 4: 使用 wait_order 等待所有阶段按顺序完成
    initial begin : process_observer_ordered
        $display("[%0t] Ordered Observer: Waiting for stage1, then stage2, then final_done IN ORDER...", $time);
        // fork-join 内多个 begin...end 块并行执行，begin...end 块内的代码串行执行
        fork
            begin
                // 阻塞等待事件按指定顺序触发
                wait_order(stage1_done, stage2_done, final_done) begin
                    $display("[%0t] Ordered Observer: All stages completed successfully in order!", $time);
                end else begin
                    // 如果 wait_order 因为其他原因 (如 $finish) 提前终止，或有其他复杂用法，会执行 else
                    // 在这个简单例子里，主要关注 begin...end 块的执行
                    $display("[%0t] Ordered Observer: Wait terminated.", $time); // 通常不执行，除非仿真结束
                end
            end
            begin
                @error_occurred;
                $display("[%0t] Ordered Observer: Error detected, terminating wait.", $time);
            end
        join_any
        disable fork; // 终止所有 fork 内的所有进程 (无论是否完成)
        $display("[%0t] Ordered Observer: Finished waiting.", $time);
    end

    // 进程 5: 使用 wait() 等待 stage2_done 的状态 (triggered)
    initial begin : process_observer_wait_state
        #5; // 稍微延迟启动，确保不是在时间0就等待
        $display("[%0t] State Waiter: Waiting until 'stage2_done' has been triggered...", $time);
        // event_name.triggered 是一个内置方法，检查事件是否已被触发过
        // @ 等待event被触发，而 wait(event.triggered) 检查的是事件的状态（仅在命名事件被触发的那个精确的仿真时间片内为真，在其他任何时间都为假）。
        wait(stage2_done.triggered);
        $display("[%0t] State Waiter: Detected 'stage2_done' has triggered at some point.", $time);
        $display("[%0t] State Waiter: Finished.", $time);
    end

    // 进程 6: 使用 wait() 监控是否出错或最终完成 (等待条件)
    initial begin : process_completion_monitor
        $display("[%0t] Completion Monitor: Waiting for 'final_done' OR 'error_occurred'...", $time);
        // 等待 final_done 或 error_occurred 中任何一个被触发
        // .triggered 检查事件是否已发生
        wait(final_done.triggered || error_occurred.triggered);

        if (final_done.triggered) begin
            $display("[%0t] Completion Monitor: Detected SUCCESSFUL completion ('final_done').", $time);
        end else if (error_occurred.triggered) begin
            $display("[%0t] Completion Monitor: Detected ERROR ('error_occurred').", $time);
        end
        $display("[%0t] Completion Monitor: Finished.", $time);
    end


    // 仿真控制
    initial begin
        #100 $finish;
    end

endmodule
